package net.ikenway.springboot.demo.Service.Implement;

import net.ikenway.springboot.demo.Dao.UserRepository;
import net.ikenway.springboot.demo.Model.Dto.UserDto;
import net.ikenway.springboot.demo.Model.Entity.User;
import net.ikenway.springboot.demo.Service.Interface.UserServiceIntf;
import net.ikenway.springboot.demo.Utils.MapperUtil;
import net.ikenway.springboot.demo.Utils.SpringContextUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import javax.persistence.EntityNotFoundException;
import javax.transaction.Transactional;
import java.util.List;

/**
 * @author MasterKenway <zk@ikenway.net>
 * @Description
 * @date Created Date 12/10/2020
 */
@Service
public class UserDetailsServiceImpl implements UserDetailsService, UserServiceIntf {
    private final UserRepository userRepository;
    private final MapperUtil mapperUtil;

    @Autowired
    public UserDetailsServiceImpl(UserRepository userRepository, MapperUtil mapperUtil) {
        this.userRepository = userRepository;
        this.mapperUtil = mapperUtil;
    }

    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        return userRepository.findByUsername(s).orElseThrow(() -> new UsernameNotFoundException("UsernameNotFound"));
    }

    @Override
    public List<UserDto> findAll() {
        return mapperUtil.mapList(userRepository.findAll(), UserDto.class);
    }

    @Override
    public User findByUsername(String username) throws UsernameNotFoundException {
        return userRepository.findByUsername(username).orElseThrow(() -> new UsernameNotFoundException("UsernameNotFound"));
    }

    @Override
    public UserDto create(User user) {
        return mapperUtil.map(userRepository.save(user), UserDto.class);
    }

    @Override
    public UserDto getUserInfo() {
        User user = SpringContextUtil.getCurrentUser();
        return mapperUtil.map(user, UserDto.class);
    }

    public void update(User user) {
        userRepository.save(user);
    }

    @Override
    public UserDto update(UserDto userDto) {
        User user = exitsOrNot(SpringContextUtil.getCurrentUser().getUserId());
        user.setName(userDto.getName());
        user.setAvatar(userDto.getAvatar());
        user = userRepository.save(user);
        return mapperUtil.map(user, UserDto.class);
    }

    public void updateIdentity(User.Identity identity, Long userId) {
        User user = userRepository.findById(userId).orElseThrow();
        user.setIdentity(identity);
        userRepository.save(user);
    }

    @Override
    public void enable(List<Long> userIds) throws EntityNotFoundException {
        for (Long userId : userIds) {
            User user = userRepository.findById(userId).orElseThrow(EntityNotFoundException::new);
            user.setEnabled(true);
            userRepository.save(user);
        }
    }

    @Override
    @Transactional
    public void disable(List<Long> userIds) throws EntityNotFoundException {
        for (Long userId : userIds) {
            User user = userRepository.findById(userId).orElseThrow(EntityNotFoundException::new);
            user.setEnabled(false);
            userRepository.save(user);
        }
    }

    @Override
    public void delete() throws Exception {
        userRepository.delete(SpringContextUtil.getCurrentUser());
    }

    @Override
    public User exitsOrNot(Long userId) throws EntityNotFoundException {
        return userRepository.findById(userId).orElseThrow(EntityNotFoundException::new);
    }
}
